package com.cacho.s2b.lesson.engine;

import com.cacho.s2b.lesson.security.Activation;
import com.cacho.s2b.lesson.security.JWTCustom;
import com.cacho.s2b.lesson.vo.ApiActivation;
import com.cacho.s2b.lesson.vo.ApiStepInfo;
import com.cacho.s2b.lesson.vo.ApiTestInfo;
import com.cacho.s2b.lesson.vo.RequestInfo;
import com.google.gson.Gson;
import io.restassured.RestAssured;
import io.restassured.http.ContentType;
import io.restassured.http.Method;
import io.restassured.response.Response;
import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

import java.util.HashMap;
import java.util.Map;

import static io.restassured.RestAssured.given;

/**
 * @Description 组装 API 发送和返回信息
 * @Author LingWei
 * @date 2023/12/31
 **/
@Setter
@Getter
@Slf4j
public class ApiTestSender {

    private String scenarioId = ""; // 对应案例id
    private String newStepName = ""; // 新测试步骤
    private ApiTestInfo tester;     // 新测试信息
    ApiActivation activation;
    ApiStepInfo lastStepInfo;       // 上个测试步骤信息（一个Scenario（场景）有多个案例）

    public ApiTestSender() {
        this("");
    } // 构造函数传入下面带参数

    // 待参数构造函数
    public ApiTestSender(String scenarioId) {
        log.info("初始化一个测试案例scenarioId：{}", scenarioId);
        this.scenarioId = scenarioId;
        this.tester = new ApiTestInfo();
    }

    // 对 newStepName 赋值
    public void nameAStep(String stepName) {
        if (!"".equals(stepName)) {
            this.newStepName = stepName;
            log.debug("新测试步骤为：{}", newStepName);
        }
    }

    // 组装接口请求参数,并对 response 赋值
    public void sendApiRequest(RequestInfo request, String apiDefName) {
        lastStepInfo = tester.getLastStepInfo();
        ApiStepInfo giveStep = null;
        if (StringUtils.isNotEmpty(newStepName)) {
            giveStep = tester.searchStep(newStepName);
            if (giveStep == null) {
                giveStep = tester.addStepRecord(newStepName);
                giveStep.setRequest(request);
            }
        }
        String fullUrl = request.getUrl().toString();
        String payload = request.getBody();
        Map<String, String> headerMap = request.getHeaders();
        ContentType contentType = request.getContentType();
        Method method = request.getMethod();
        Response response = null;
        try {
            response = fetchApiResponse(fullUrl, payload, headerMap, contentType, method);
            log.info("接口请求返回码：{}", response.statusCode());
            log.info("接口请求响应信息：\n{}", response.asPrettyString());
            // response赋值到 ApiStepInfo， 后面断言需要
            lastStepInfo.setResponse(response);
        } catch (Exception e) {
            lastStepInfo.setException(e); //赋值异常信息
            log.warn("API请求出现异常：{}", e.getMessage());
        }
        if (giveStep != null) {
            giveStep.setApiDefName(apiDefName);
            giveStep.setResponse(response);
        }
    }

    // 接口请求并获取response响应信息
    private Response fetchApiResponse(String fullUrl, String payload, Map<String, String> headerMap,
                                      ContentType contentType, Method method) throws Exception {
        Response response;
        // 处理 payload需要 jwt格式
        String groupId = headerMap.getOrDefault("GroupId", "");
        String jwtPayloadType = headerMap.getOrDefault("JWTPayloadType", "payload");
        String isJWT = headerMap.getOrDefault("BodyIsJWT", "");
        String alg = headerMap.getOrDefault("JWTAlg", "");
        activation = lastStepInfo.getRequest().getActivation();
        boolean bodyIsJWT = method.toString().equals("POST") || method.toString().equals("PATCH");
        if (activation != null && bodyIsJWT && isJWT.equalsIgnoreCase("Yes")) {
            Map<String, String> payload0 = new HashMap<>();
            payload0.put(jwtPayloadType, payload);
            payload = JWTCustom.generateJWT(30L, payload0, activation.getPrivateKey(), alg);
            headerMap.remove("JWTPayloadType");
            headerMap.remove("BodyIsJWT");
            headerMap.remove("JWTAlg");
        } else if (activation != null && method.toString().equals("GET")) {
            String token = JWTCustom.generateJWT(30L, null, activation.getPrivateKey(), alg);
            headerMap.put("JWTToken",token);
            headerMap.remove("GroupId");
        }
        if (activation == null || StringUtils.isEmpty(groupId)){
            RestAssured.reset();
            RestAssured.useRelaxedHTTPSValidation();  // 忽略 https SSL校验
        }
        log.info("请求 Headers 为：{}", headerMap);
        log.info("请求 payload 为：{}", payload);
        log.info("请求 method 为：{}; Url为：{}", method, fullUrl);
        switch (method) {
            case POST:
                if (StringUtils.isEmpty(payload)) {
                    response = given().contentType(contentType).headers(headerMap).when().post(fullUrl);
                } else {
                    response = given().contentType(contentType).headers(headerMap).body(payload).when().post(fullUrl);
                }
                break;
            case GET:
                if (StringUtils.isEmpty(payload)) {
                    response = given().contentType(contentType).headers(headerMap).when().get(fullUrl);
                } else {
                    response = given().contentType(contentType).headers(headerMap).body(payload).when().get(fullUrl);
                }
                break;
            default:
                throw new Exception("不支持的请求。");
        }
        return response;
    }

}
